package com.geovis.emergency.spd.biz.system.service.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.geovis.emergency.spd.biz.system.service.ISystemDeptUserService;
import com.geovis.emergency.spd.biz.system.service.ISystemParamService;
import com.geovis.emergency.spd.biz.system.service.ISystemUserService;
import com.geovis.emergency.spd.biz.system.mapper.SystemDeptMapper;
import com.geovis.emergency.spd.biz.system.service.ISystemDeptService;
import com.geovis.emergency.spd.entity.basic.entity.BasicLabel;
import com.geovis.emergency.spd.entity.pc.pojo.enums.StatusEnum;
import com.geovis.emergency.spd.entity.pc.pojo.vo.SystemDeptVo;
import com.geovis.emergency.spd.entity.system.entity.SystemDept;
import com.geovis.emergency.spd.entity.system.entity.SystemDeptUser;
import com.geovis.emergency.spd.entity.system.entity.SystemUser;
import com.geovis.emergency.spd.entity.system.pojo.vo.SystemDeptTreeVO;
import com.geovis.emergency.spd.entity.system.pojo.vo.SystemUserVo;
import com.geovis.emergency.spd.redis.RedisUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 机构表 服务实现类
 * </p>
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class SystemDeptServiceImpl extends ServiceImpl<SystemDeptMapper, SystemDept> implements ISystemDeptService {

    private final ISystemUserService systemUserService;
    private final ISystemParamService sysParamService;

    private static String DEPT_TREE_CACHE_KEY = "system:dept:tree";
    private final ISystemDeptUserService systemDeptUserService;
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void removeByIdList(Set<String> idList) {

        if (CollUtil.isEmpty(idList)) {
            return;
        }
        //1、刪除本身
        removeByIds(idList);

        //2、删除用户部门关联关系，解除用户关联部门
        systemDeptUserService.remove(new UpdateWrapper<SystemDeptUser>().lambda().in(SystemDeptUser::getDeptId, idList));
        idList.stream().forEach(deptId->{
            LambdaUpdateWrapper<SystemUser> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(SystemUser::getDeptId, deptId);
            updateWrapper.set(SystemUser::getDeptId, null);
            systemUserService.update(updateWrapper);
        });


        //3、刪除孩子节点
        List<SystemDept> list = baseMapper.selectList(Wrappers.lambdaQuery(SystemDept.class).select(SystemDept::getId).in(SystemDept::getParentId, idList));
        Set<String> childrenIdList = CollUtil.set(false);
        list.forEach(systemDept -> childrenIdList.add(systemDept.getId()));
        removeByIdList(childrenIdList);

    }

    /**
     * 获取部门树，只以 参数中需要显示的部门根节点为根基
     * @return
     */
    @Override
    public List<SystemDeptTreeVO> tree() {
        String canShowDeptRoot = sysParamService.getValueById("can_show_dept_root");
        return baseMapper.tree(StrUtil.split(canShowDeptRoot,","));
    }

    @Override
    public List<SystemDeptTreeVO> deptTree() {
        //取出根节点部门parent=null
        List<SystemDept> rootDepts=baseMapper.selectList(Wrappers.lambdaQuery(SystemDept.class).isNull(SystemDept::getParentId).orderByAsc(SystemDept::getIdx));

        //取出非根节点部门
        List<SystemDept> allDept=baseMapper.selectList(Wrappers.lambdaQuery(SystemDept.class).isNotNull(SystemDept::getParentId).orderByAsc(SystemDept::getIdx));
        List<SystemDeptTreeVO> rootDeptTreeVo=new ArrayList<>();
        //循环处理根节点，然后递归处理子节点
        for(SystemDept rootDept:rootDepts)
        {
            SystemDeptTreeVO rootDeptVo=SystemDeptTreeVO.fromDept(rootDept);
            buildChildDeptTreeVo(rootDeptVo,allDept);
            rootDeptTreeVo.add(rootDeptVo);
        }
        return rootDeptTreeVo;
    }



    /**
     * 递归构造子树
     */
    private void buildChildDeptTreeVo(SystemDeptTreeVO parentDept,List<SystemDept> allDept)
    {
        List<SystemDept> childDepts=allDept.stream().filter(d->d.getParentId().equals(parentDept.getId())).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(childDepts))
        {
            parentDept.setHasChildren(false);
            return;
        }
        List<SystemDeptTreeVO> treeVos=new ArrayList<>();
        for(SystemDept childDept:childDepts)
        {
            //这里要先判断refId是否有值，如果有则需要替换
            if(StringUtils.hasText(childDept.getRefId()))
            {
                String refId=childDept.getRefId();
                childDept=allDept.stream().filter(d->d.getId().equals(refId)).findFirst().get();
            }
            SystemDeptTreeVO childDeptVo=SystemDeptTreeVO.fromDept(childDept);
            buildChildDeptTreeVo(childDeptVo,allDept);
            treeVos.add(childDeptVo);
        }
        parentDept.setHasChildren(true);
        parentDept.setChildren(treeVos);
    }

    @Override
    public void deleteTreeCache() {
        RedisUtil.del(DEPT_TREE_CACHE_KEY);
        return;
    }

    @Override
    public List<SystemDept> getRootDepts() {

        return baseMapper.selectList(Wrappers.lambdaQuery(SystemDept.class).isNull(SystemDept::getParentId).orderByAsc(SystemDept::getIdx));
    }

    @Override
    public List<SystemDept> getChildDepts(String parentId) {
        //这里注意，若表中SystemDept中的refId有值，则返回的数据，是refId指向的数据
        List<SystemDept> result=new ArrayList<>();
        List<SystemDept> depts=baseMapper.selectList(Wrappers.lambdaQuery(SystemDept.class).eq(SystemDept::getParentId, parentId).orderByAsc(SystemDept::getIdx));
        depts.stream().forEach(dept->{
            if(StringUtils.hasText(dept.getRefId()))
            {
                SystemDept refDetpt=baseMapper.selectOne(Wrappers.lambdaQuery(SystemDept.class).eq(SystemDept::getId, dept.getRefId()));
                result.add(refDetpt);
            }
            else
            {
                result.add(dept);
            }

        });
        return result;
    }

    @Override
    public List<SystemDeptVo> queryChildDepts(String parentId) {
        List<SystemDeptVo> result=new ArrayList<>();
        List<SystemDept> depts=baseMapper.selectList(Wrappers.lambdaQuery(SystemDept.class).eq(SystemDept::getParentId, parentId).orderByAsc(SystemDept::getIdx));
        depts.stream().forEach(dept->{
            SystemDeptVo  deptVo=new SystemDeptVo();

            if(StringUtils.hasText(dept.getRefId()))
            {
                SystemDept refDetpt=baseMapper.selectOne(Wrappers.lambdaQuery(SystemDept.class).eq(SystemDept::getId, dept.getRefId()));
                BeanUtils.copyProperties(refDetpt,deptVo);

            }
            else
            {
                BeanUtils.copyProperties(dept,deptVo);
            }
            if(hasChildDepts(deptVo.getId()))
            {
                deptVo.setLeaf(0);
            }
            result.add(deptVo);

        });
        return result;
    }

    private boolean hasChildDepts(String id)
    {
        Long count=baseMapper.selectCount(Wrappers.lambdaQuery(SystemDept.class).eq(SystemDept::getParentId, id));
        return count>0;
    }

    @Override
    public List<SystemUserVo> getUsers(List<String> deptIds, List<String> excludeUserIds,String keyword) {
        return baseMapper.getUsers(deptIds,excludeUserIds,keyword);
    }

    @Override
    public List<SystemUserVo> queryAllChildDeptUsers(String parentDeptId) {
        List<SystemDeptVo> childDepts=this.queryChildDepts(parentDeptId);
        if(CollectionUtils.isEmpty(childDepts))
        {
            //如果没有子部门，返回当前部门的员工
            return this.getUsers(Arrays.asList(parentDeptId),null,null);
        }
        List<String> deptIds=childDepts.stream().map(d->d.getId()).collect(Collectors.toList());
        return this.getUsers(deptIds,null,null);

    }

    @Override
    public boolean checkLeafNode(String deptId) {
        return this.count(Wrappers.lambdaQuery(SystemDept.class).eq(SystemDept::getParentId, deptId))==0;
    }

    @Override
    public List<String> getLeafDeptUserIds(Set<String> deptIds) {
        //这里deptIds，可能是单个，也可能是页面传过来的父子结构的数据
        List<String> leafDeptIds=new ArrayList<>();
        deptIds.stream().forEach(deptId->{
            findLeafDepts(deptId,leafDeptIds);

        });
        List<SystemDeptUser> deptUsers=systemDeptUserService.list(Wrappers.lambdaQuery(SystemDeptUser.class).in(SystemDeptUser::getDeptId, leafDeptIds));
        return deptUsers.stream().map(SystemDeptUser::getUserId).collect(Collectors.toList());

    }

    /**
     * 递归查找叶子部门的id
     */
    private void findLeafDepts(String parentDeptId,List<String> leafDeptIds)
    {
        List<SystemDept> childDepts=this.list(Wrappers.lambdaQuery(SystemDept.class).eq(SystemDept::getParentId, parentDeptId));
        if(CollectionUtils.isEmpty(childDepts))
        {
            leafDeptIds.add(parentDeptId);
            return;
        }
        childDepts.stream().forEach(dept->{
            findLeafDepts(dept.getId(),leafDeptIds);
        });

    }

}
